Skip to content

Cancel remaining fields on exceptions #238

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mgorven
Copy link

@mgorven mgorven commented May 13, 2025

gather() returns when the first exception is raised, but does not cancel any remaining tasks. These continue to run which is inefficient, and can also cause problems if they access shared resources like database connections.

Fixes: #236

@Cito
Copy link
Member

Cito commented May 13, 2025

Thank you @mgorven - will have a look later this week or on the weekend.

Copy link

codspeed-hq bot commented May 13, 2025

CodSpeed Performance Report

Merging #238 will not alter performance

Comparing mgorven:cancel-tasks (74dae01) with main (0107e30)

Summary

✅ 14 untouched benchmarks

@mgorven mgorven force-pushed the cancel-tasks branch 2 times, most recently from 322f5f6 to 6456782 Compare May 13, 2025 23:23
for field in awaitable_fields:
tasks[create_task(results[field])] = field # type: ignore[arg-type]

done, pending = await wait(tasks, return_when=FIRST_EXCEPTION)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other approach is to allow all fields to finish executing and then raise the exception.

for task in pending:
task.cancel()

results.update((tasks[task], task.result()) for task in done)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This maintains the previous behaviour of not setting any results if an exception is raised, but I could change this to set the results we do have and then raise the exception.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this behave in-line with the spec regarding partial results?

https://spec.graphql.org/draft/#sec-Handling-Execution-Errors

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine because the potentially completed fields are siblings of the field with an exception, and the exception is propagated to the parent which will either be null or propagate further up. In either case these siblings field won't be present in the response.

gather() returns when the first exception is raised, but does not cancel
any remaining tasks. These continue to run which is inefficient, and can
also cause problems if they access shared resources like database
connections.

Fixes: graphql-python#236
@mgorven
Copy link
Author

mgorven commented May 14, 2025

Check is failing because coverage is not 100%, but this is because completed = True in the test case is not executed which is exactly what we're testing for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants